透明窗口在 Windows 上有哪些限制?
考察点
transparent: true的代价- 异形窗口、阴影、点击穿透的实现边界
参考答案
1. 基本开法
const win = new BrowserWindow({
transparent: true,
frame: false,
hasShadow: false, // Windows 上透明和系统阴影经常不能同时要
backgroundColor: '#00000000',
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
},
});
页面背景用 background: transparent,圆角和异形由 CSS 画。
2. Windows 上的限制
- 系统阴影基本没有。
hasShadow: true会出一口黑底或直接失效。阴影要用 CSSbox-shadow,或者窗外再垫一层 - 不能和部分硬件加速路径共存。老显卡上透明窗口会花、会透出桌面残影。需要准备关闭透明的降级开关
- 点击行为:透明像素默认仍属于窗口。要做到“透明处点穿到桌面”,用
setIgnoreMouseEvents(true, { forward: true }),再在需要点击的 DOM 区域把鼠标事件打开。forward: true才能继续收到鼠标移动,用来判断现在是不是在可点击区域上 - 圆角和最大化:最大化时圆角要去掉,否则四个角透出桌面
- 截图和录屏:透明区域在部分采集里会变成黑色或白色
macOS 对透明和阴影友好一些,仍要注意全屏、多显示器拖拽时的重绘。
3. 点击穿透示例
// preload 把渲染进程的命中结果告诉主进程
ipcMain.on('hover:interactive', (event, interactive) => {
const win = BrowserWindow.fromWebContents(event.sender);
// interactive 为 false 时,点击落到窗口后面
win?.setIgnoreMouseEvents(!interactive, { forward: true });
});
渲染进程根据 mousemove 的目标是不是按钮来发这个事件,并且要节流,否则每像素一次 IPC。
4. 什么时候不要用透明窗口
普通矩形主界面用无边框 + 不透明背景就够了。透明窗口只留给悬浮球、歌词、小组件。它更吃 GPU,也更容易在远程桌面里出问题。
面试话术
透明窗口是 frame:false 加 transparent。Windows 上系统阴影基本要放弃,改用 CSS。透明像素默认仍会挡住鼠标,点穿要用 setIgnoreMouseEvents,并用 forward 保留 mousemove 来切换可点区域。主界面不要为了圆角去开整窗透明。
常见追问
- 圆角一定要透明窗口吗? macOS 可以用隐藏标题栏加系统圆角。Windows 11 有系统圆角能力,但 Electron 里不总是好控,很多团队仍用 CSS。
- 穿透开了之后窗口收不到点击? 说明切回
ignore: false的区域判断漏了,或者 IPC 太慢,鼠标已经点下去才切回来。命中检测要在本地做,少依赖往返。